﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using SQLiteTest;

namespace SQLiteTestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            string userInput = "";
            while (userInput != "exit")
            {
                WriteMenu();
                userInput = Console.ReadLine();
                HandleUserInput(userInput);
            }
        }

        #region Properties

        private static SQLite2EFTest2Entities sContext;
        private static SQLiteTest.SQLite2EFTest2Entities Context
        {
            get
            {
                if (sContext == null)
                    sContext = new SQLite2EFTest2Entities();
                return sContext;
            }
        }

        #endregion Properties

        #region Methods

        private static void WriteMenu()
        {
            Console.WriteLine();
            Console.WriteLine("0 : Init DB");
            Console.WriteLine("1 : Write DB");
            Console.WriteLine("2 : Delete a B");
            Console.WriteLine("3 : Delete a D");
        }

        private static void HandleUserInput(string userInput)
        {
            switch (userInput)
            {
                case "0":
                    InitDB();
                    break;
                case "1":
                    WriteDB();
                    break;
                case "2":
                    DeleteB();
                    break;
                case "3":
                    DeleteD();
                    break;
                default:
                    break;
            }
        }

        private static void ClearDB()
        {
            Console.Write("Clearing DB... ");
            foreach (C c in Context.C)
            {
                Context.DeleteObject(c);
            }
            Context.SaveChanges();
            //Context.Refresh(System.Data.Objects.RefreshMode.StoreWins, Context.B);
            foreach (B b in Context.B)
            {
                Context.DeleteObject(b);
            }
            Context.SaveChanges();
            //Context.Refresh(System.Data.Objects.RefreshMode.StoreWins, Context.B);
            foreach (A a in Context.A)
            {
                Context.DeleteObject(a);
            }
            Context.SaveChanges();
            //Context.Refresh(System.Data.Objects.RefreshMode.StoreWins, Context.B);
            foreach (D d in Context.D)
            {
                Context.DeleteObject(d);
            }
            Context.SaveChanges();
            //Context.Refresh(System.Data.Objects.RefreshMode.StoreWins, Context.B);
            Console.WriteLine("done.");
        }

        private static void InitDB()
        {
            ClearDB();
            InitA();
            InitB();
            InitC();
            InitD();
        }

        private static void InitA()
        {
            Console.Write("Adding some A to 'A's... ");
            for (int i = 0; i < 3; i++)
            {
                Context.A.AddObject(new A());
            }
            Console.WriteLine("done.");
            Console.WriteLine("Saving... ");
            Context.SaveChanges();
            Console.WriteLine("done.");
        }

        private static void InitB()
        {
            Console.Write("Adding some B to 'B's... ");
            //string bName = "b";
            int i = 0;
            foreach (var a in Context.A)
            {
                for (int j = 0; j < i + 1; j++)
                {
                    Context.B.AddObject(
                        new B()
                        {
                            A_Id = a.Id,
                            Name = Char.ConvertFromUtf32(58 + i + j).ToString()
                        });
                }
                //bName += "b";
                i += 1;
            }
            Console.WriteLine("done.");
            Console.WriteLine("Saving... ");
            Context.SaveChanges();
            Console.WriteLine("done.");
        }

        private static void InitC()
        {
            Console.Write("Adding some C to 'C's... ");
            int i = 0;
            Collection<C> cs = new Collection<C>();
            foreach (var b in Context.B)
            {
                for (int j = 0; j < i + 1; j++)
                {
                    C c = new C()
                        {
                            Id = i.ToString() + j.ToString(),
                            B_A_Id = b.A_Id,
                            B_Name = b.Name
                        };
                    Context.C.AddObject(
                        c
                        );
                    cs.Add(c);
                }
                i += 1;
            }
            Console.WriteLine("done.");

            Console.WriteLine("Saving... ");
            Context.SaveChanges();
            Console.WriteLine("done.");
        }

        private static void InitD()
        {
            Console.Write("Adding some D to 'D's... ");
            D d1 = new D();
            Context.D.AddObject(d1);
            Console.WriteLine("Saving... ");
            Context.SaveChanges();
            Console.WriteLine("done.");

            D d2 = new D();
            Context.D.AddObject(d2);
            int bCount = Context.B.Count();
            for (int i = 0; i < bCount / 3; i++)
            {
                B firstB = Context.B.First(new Func<B, bool>(
                    b =>
                    {
                        return b.D_Id == null;
                    }));
                firstB.D_Id = d1.Id;
            }
            for (int i = bCount / 3; i < (2 * bCount / 3) + 1; i++)
            {
                B firstB = Context.B.First(new Func<B, bool>(
                    b =>
                    {
                        return b.D_Id == null;
                    }));
                firstB.D_Id = d2.Id;
            }
            Console.WriteLine("done.");

            Console.WriteLine("Saving... ");
            Context.SaveChanges();
            Console.WriteLine("done.");
        }

        private static void WriteDB()
        {
            Console.WriteLine("'A's:");
            foreach (A a in Context.A)
            {
                Console.WriteLine("  " + a.ToString());
            }
            Console.WriteLine("'B's:");
            foreach (B b in Context.B)
            {
                Console.WriteLine("  " + b.ToString());
            }
            Console.WriteLine("'C's:");
            foreach (C c in Context.C)
            {
                Console.WriteLine("  " + c.ToString());
            }
            Console.WriteLine("'D's:");
            foreach (D d in Context.D)
            {
                Console.WriteLine("  " + d.ToString());
            }
        }

        private static void DeleteB()
        {
            Console.Write("Deleting first B... ");
            try
            {
                Context.B.DeleteObject(Context.B.First());
                Context.SaveChanges();
            }
            catch (ArgumentNullException ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            Console.WriteLine("done.");
        }

        private static void DeleteD()
        {
            throw new NotImplementedException();
        }

        #endregion Methods
    }
}
